$.fn.serializeObject = function () {
    var o = {};
    var a = this.serializeArray();
    $.each(a, function () {
        if (this.name.substr(-2) == "[]") {
            this.name = this.name.substr(0, this.name.length - 2);
            o[this.name] = [];
        }
        if (o[this.name]) {
            if (!o[this.name].push) {
                o[this.name] = [o[this.name]];
            }
            o[this.name].push(this.value || '');
        } else {
            o[this.name] = this.value || '';
        }
    });
    return o;
};

$.noty.defaults.layout = 'topCenter';
$.noty.defaults.theme = 'bootstrapTheme';
$.noty.defaults.maxVisible = 3;

!function () {
    var dataValue = function (data, key) {
        for (var i in data) {
            var row = data[i];
            if (row.name == key)
                return row.value;
        }
        return null;
    };
    var dataConvert = function (data) {
        var paramData = [
            {name: 'offset', value: dataValue(data, 'iDisplayStart')},
            {name: 'limit', value: dataValue(data, 'iDisplayLength')},
            {name: 'keyword', value: dataValue(data, 'sSearch')},
            {name: 'order_key', value: dataValue(data, 'mDataProp_' + dataValue(data, 'iSortCol_0'))},
            {name: 'order_value', value: dataValue(data, 'sSortDir_0')}
        ];
        return paramData;
    };
    var handleTreeNodes = function (nodes, show_feature, tools, textName) {
        for (var i in nodes) {
            var node = nodes[i];
            node.data = $.extend(true, {}, node);
            var classes = (node.status == 'Active') ? 'active-span' : 'deactivated-span',
                feature = (show_feature && node.feature) ? '<i class="fa fa-fw fa-star"></i>' : '';
            if (node.icon) {
                node.icon = node.icon + '?imageView2/1/w/150/h/150/q/75';
            }
            node.text = '<span class="' + classes + '">' + (textName && node[textName] || node.text) + feature + (tools || '') + '</span>';
            if (node.children) {
                handleTreeNodes(node.children, show_feature, tools, textName);
            }
        }
    }

    var utils = {
        /**
         * 正则表达式
         */
        regexp: {
            tel: /^1[0-9]{10}$/
        },

        /**
         * 时间格式化
         */
        dateTimeFormat: function (date) {
            if (!date) return '';
            return moment(date).format('YYYY-MM-DD HH:mm:ss');
        },

        /**
         * 日期格式化
         */
        dateFormat: function (date) {
            if (!date) return '';
            return moment(date).format('YYYY-MM-DD');
        },

        /**
         * 导航参数
         */
        querys: function () {
            var querys = {}, hashes = location.href.slice(location.href.lastIndexOf('?') + 1).split('&');
            for (var i in hashes) {
                var hash = hashes[i].split('=');
                querys[hash[0]] = hash[1];
            }
            return querys;
        },

        /**
         * 请求异常
         */
        requestError: function (err) {
            if (err.status == 401) {
                if (window.isLoginShow) {
                    return;
                }
                window.isLoginShow = true;
                var html = $(utils.getHtml('login', {host: HOST}));
                html.modal({backdrop: 'static'}).on('hidden.bs.modal', function () {
                    html.remove();
                    window.isLoginShow = false;
                });
                var form = $('form', html).formValidation(utils.getValidation({
                    tel: {
                        validators: {
                            notEmpty: {message: '手机号不能为空'},
                            regexp: {regexp: utils.regexp.tel, message: '手机号格式不正确'}
                        }
                    },
                    password: {
                        validators: {notEmpty: {message: '密码不能为空'}}
                    }
                })).on('success.form.fv', function (e) {
                    e.preventDefault();
                    var $form = $(e.target), fv = $form.data('formValidation');

                    publicApi('login', $form.serialize()).then(function (result) {
                        if (result.success) {
                            location.reload(true);
                        } else {
                            utils.fixedAlert('warning', result.message || '登录失败');
                        }
                    }, function () {
                        utils.fixedAlert('warning', '登录失败');
                    }).always(function () {
                        if (fv.getSubmitButton()) {
                            fv.disableSubmitButtons(false);
                        }
                    });
                });
            } else if (err.status == 403) {
                utils.fixedAlert('warning', '你没有权限进行此操作!');
            } else if (err.status == 500) {
                utils.fixedAlert('warning', '服务异常');
            }
        },

        /**
         * 弹出提示框
         */
        fixedAlert: function (type, text) {
            noty({type: type, text: text, timeout: 1500});
        },

        /**
         * 获取Html
         */
        getHtml: function (name, data) {
            var temp = $('#' + name + '-template').html();
            return Handlebars.compile(temp)(data);
        },

        /**
         * 获取 Validation
         */
        getValidation: function (fields) {
            return {
                framework: 'bootstrap',
                icon: {
                    valid: 'glyphicon glyphicon-ok',
                    invalid: 'glyphicon glyphicon-remove',
                    validating: 'glyphicon glyphicon-refresh'
                },
                fields: fields
            }
        },

        /**
         * 处理拖动后排序
         */
        sortTree: function (menu, data, callback) {
            var children = menu.jstree(true).get_json(data.parent).children;
            var sorts = [];
            for (var i in children) {
                sorts.push({order_by: i, id: children[i].id})
            }
            callback(sorts).then(function (data) {
                if (data.success) {
                    utils.fixedAlert('success', '移动成功');
                } else {
                    utils.fixedAlert('warning', '移动失败');
                    menu.jstree('refresh');
                }
            });
        },

        /**
         * 添加过虑器
         */
        addFilterGroupbtn: function (pane, data, defaultValue) {
            $('.content-header', pane).append(utils.getHtml('table_filter_groupbtn', data));

            var dataValue = defaultValue || store.get(data.store_key || location.hash + '-' + data.name);
            if (dataValue) {
                var sel = $('.filter-' + data.name + ' button[data-value="' + dataValue + '"]', pane);
                if (sel.length) {
                    $('.filter-' + data.name + ' .active', pane).removeClass('active');
                    sel.addClass('active');
                }
            }
        },

        /**
         * 添加过虑器
         */
        addFilterDropdown: function (pane, data, defaultValue) {
            $('.content-header', pane).append(utils.getHtml('table_filter_dropdown', data));

            var dataValue = defaultValue || store.get(data.store_key || location.hash + '-' + data.name);
            if (dataValue) {
                var sel = $('.filter-' + data.name + ' li[data-value="' + dataValue + '"]', pane);
                if (sel.length) {
                    var filter = sel.parents('.filter-list');
                    var btn = filter.find('.label-btn');
                    btn.attr('data-value', dataValue).html(sel.text());
                }
            }
        },

        /**
         * 添加过虑器
         */
        addFilterLabel: function (pane, data) {
            $('.content-header .filter-list[data-name="' + data.name + '"]', pane).remove();
            $('.content-header', pane).append(utils.getHtml('filter_label', data));
        },

        /**
         * 添加过虑器
         */
        getPills: function (data) {
            return utils.getHtml('pills', data)
        },

        /**
         * 获取按钮数组
         */
        groupBtns: function (data) {
            if (!data) {
                return '';
            }
            return utils.getHtml('group_buttons', data);
        },

        /**
         * 右边工具按钮
         */
        addTools: function (pane, data) {
            $('.content-header', pane).append('<div class="pull-right"><div class="btn-tools">' + utils.groupBtns(data) + '</div></div>');
        },

        /**
         * 获取过虑值通过名字
         */
        filterValue: function (pane, name) {
            return $('.filter-' + name + ' li.active,.filter-' + name + ' button.active', pane).attr('data-value');
        },

        /**
         * 转换 Fields
         */
        convertFields: function (fields_arrays, exclude) {
            var fields = {};
            for (var i in fields_arrays) {
                var array = fields_arrays[i];
                var field = {
                    type: array[1],
                    label: array[2]
                }
                if (array.length > 3) {
                    field.validators = array[3];
                }
                if (array.length > 4) {
                    if ($.isArray(array[4])) {
                        field.options = array[4];
                    } else {
                        field.options = dicts[array[4]];
                    }
                }
                fields[array[0]] = field;
            }
            for (var i in exclude) {
                delete fields[exclude[i]];
            }
            return fields;
        },

        /**
         * 设置过虑参数
         * @param paramData
         * @param pane
         */
        setFilterParams: function (paramData, pane) {
            $('.filter-list', pane).each(function () {
                var self = $(this)
                var name = self.attr('data-name');
                var value = $('li.active,button.active', self).attr('data-value');
                if (!value) {
                    value = self.attr('data-value');
                }
                paramData.push({name: name, value: value});
            });
            return paramData;
        },

        /**
         * 初始化表格
         */
        dataTable: function (pane, data, handles) {
            //列数组转对象
            var arrays = data.columns_arrays;
            if (arrays) {
                var columns = [];
                for (var i in arrays) {
                    var array = arrays[i];
                    var column = {
                        data: array[0],
                        title: array[1]
                    }
                    if (array.length > 2) {
                        column.orderable = array[2];
                    }
                    if (array.length > 3) {
                        column.render = array[3];
                    }
                    if (array.length > 4 && array[4]) {
                        column.className = array[4];
                    }
                    if (array.length > 5 && array[5] === false) {
                        column.visible = false;
                    }
                    columns.push(column);
                }
                data.columns = columns;
            }

            //设置浮动表头
            var fixedHeader = {headerOffset: 42};
            if (data.fixedHeader === false) {
                fixedHeader = false;
            }
            //初始化表格
            var table = $('.table', pane).dataTable({
                    serverSide: true,
                    ajaxSource: true,
                    paginate: (data.paginate !== false),
                    info: (data.info !== false),
                    filter: (data.filter !== false),
                    fixedHeader: fixedHeader,
                    fnServerData: function (source, params, callback) {
                        var paramData = dataConvert(params);
                        utils.setFilterParams(paramData, pane);
                        data.fnServerData(paramData).then(function (json) {
                            callback({
                                iTotalRecords: json.count,
                                iTotalDisplayRecords: json.count,
                                aaData: json.rows
                            });
                        });
                    },
                    fnRowCallback: function (row, data) {
                        var self = $(row);
                        if (data.id) {
                            self.addClass('row_' + data.id);
                        }
                        return row;
                    },
                    fnInitComplete: function () {
                        if (fixedHeader) {
                            table.append('<tfoot></tfoot>');
                            $(" > thead tr", table).clone().appendTo($("tfoot", table));
                        }
                    },
                    columns: data.columns,
                    sorting: data.sorting,
                    rowReorder: data.rowReorder,
                    columnDefs: data.columnDefs,
                    language: {
                        lengthMenu: "显示 _MENU_ 项结果",
                        zeroRecords: "没有匹配结果",
                        info: "显示第 _START_ 至 _END_ 项结果，共 _TOTAL_ 项",
                        infoEmpty: "显示第 0 至 0 项结果，共 0 项",
                        search: "搜索:",
                        emptyTable: "表中数据为空",
                        loadingRecords: "载入中...",
                        infoThousands: ",",
                        paginate: {
                            first: "首页",
                            previous: "上页",
                            next: "下页",
                            last: "末页"
                        }
                    }
                }
            ).on('click', 'tbody .filterable', function () {
                var self = $(this), text = self.text(), value, name;
                if (self.attr('data-value') && self.attr('data-name')) {
                    value = self.attr('data-value');
                    name = self.attr('data-name');
                } else {
                    var cell = table.api().cell(this);
                    value = cell.data();
                    if (!value || !text) {
                        return false;
                    }
                    name = data.columns[cell.index().column].data;
                    if ($('.filter-span[data-name="' + name + '"]', pane).length) {
                        return false;
                    }
                }
                var params = {value: value, text: text, name: name};
                utils.addFilterLabel(pane, params);
                table.api().draw();
            });

            //初始化过虑事件
            $('.filter-list li,.filter-list button', pane).click(function () {
                var self = $(this);
                if (self.hasClass('dropdown-toggle')) {
                    return;
                }
                var dataValue = self.attr('data-value'), downdrop = self.parents('.dropdown-group');
                if (downdrop.length) {
                    var btn = downdrop.find('.label-btn');
                    filter = downdrop.parents('.filter-list');
                    btn.attr('data-value', dataValue).html(self.text());

                    store.set(filter.attr('store-key') || location.hash + '-' + filter.attr('data-name'), dataValue);

                    //在重绘前回调
                    if (handles && handles.filter) {
                        handles.filter(filter, btn);
                    }
                    return table.api().draw();
                }
                var filter = self.parents('.filter-list');
                if (!filter.hasClass('dropdown-filter')) {
                    $('li,button', filter).removeClass('active');
                    self.addClass('active');

                    store.set(filter.attr('store-key') || location.hash + '-' + filter.attr('data-name'), dataValue);

                    //在重绘前回调
                    if (handles && handles.filter) {
                        handles.filter(filter, self);
                    }
                    return table.api().draw();
                }
            });

            //初始化删除过虑
            $('.content-header', pane).on('click', '.filter-remove', function () {
                $(this).parents('.filter-list').remove();
                table.api().draw();
            });

            return table;
        },

        /**
         * 初始化表格事件
         */
        tableEvent: function (table, callback) {
            return function () {
                var idx = $(this).parents('.child-wrapper').attr('data-index');
                if (!idx) {
                    idx = table.api().row($(this).parents('tr')).index();
                }
                var rowData = table.api().row(idx).data();
                callback.call(this, idx, rowData);
            }
        },

        /**
         * dictRender
         */
        dictRender: function (type) {
            return function (value) {
                var dict = utils.dict(type, value);
                if (!dict) {
                    return '';
                }
                if (!dict.color) {
                    return dict.text;
                }
                return '<span class="badge" style="background-color: ' + dict.color + '!important;">' + dict.text + '</span>';
            }
        },

        /**
         * priceRender
         */
        priceRender: function () {
            return function (price) {
                var price = parseFloat(price);
                if (!price) {
                    return '';
                }
                return '<div class="price">' + price.toFixed(2) + '</div>';
            }
        },

        /**
         * dateTimeRender
         */
        dateTimeRender: function () {
            return utils.dateTimeFormat;
        },

        /**
         * dateRender
         */
        dateRender: function () {
            return utils.dateFormat;
        },

        /**
         * imageRender
         */
        imageRender: function (size) {
            return function (image) {
                if (!image) return '';
                if (size === undefined) {
                    size = '?imageView2/1/w/150/h/150/q/75';
                }
                return '<img src="' + image + size + '">';
            }
        },

        /**
         * badgeRender
         */
        badgeRender: function (className) {
            return function (val) {
                return '<span class="badge ' + (className || 'bg-yellow') + '">' + val + '</span>';
            }
        },

        /**
         * nameRender
         */
        nameRender: function (len) {
            return function (name) {
                return '<div style="max-width: ' + (len || 140) + 'px; word-break: break-all;">' + (name || '') + '</div>';
            }
        },

        /**
         * columnRender
         */
        columnRender: function (column, len) {
            return function (id, type, row) {
                if (len) {
                    return '<div style="max-width: ' + (len || 140) + 'px;">' + (row[column] || '') + '</div>';
                }
                return row[column]
            }
        },

        /**
         * 初始化Input,  日期时间选择等
         */
        initInputs: function (html, data, form) {
            var datepickers = data.datepickers, datetimepicker = data.datetimepicker, values = data.data;
            if (datepickers) {
                var handleDate = function (key, date) {
                    if (values && values[key]) {
                        values[key] = moment(values[key]).format('YYYY-MM-DD');
                    }
                    $('input[name="' + key + '"]', form).datepicker(date).on('changeDate', function (e) {
                        form.formValidation('revalidateField', key);
                    });
                }
                for (var key in datepickers) {
                    handleDate(key, datepickers[key]);
                }
            }
            if (datetimepicker) {
                var handleDatetime = function (key, datetime) {
                    if (values && values[key]) {
                        values[key] = moment(values[key]).format('YYYY-MM-DD HH:mm');
                    }
                    $('input[name="' + key + '"]', form).datetimepicker(datetime).on('dp.change', function (e) {
                        form.formValidation('revalidateField', key);
                    });
                }
                for (var key in datetimepicker) {
                    handleDatetime(key, datetimepicker[key]);
                }
            }
        },

        /**
         * 处理删除
         */
        handDelete: function (table, data, alert) {
            return function (result) {
                if (result.success) {
                    if (alert) {
                        utils.fixedAlert('success', '删除' + data.name + '成功');
                    }
                    table.api().draw(false);
                    if (table.analyse) {
                        table.analyse();
                    }
                } else {
                    if (alert) {
                        utils.fixedAlert('warning', result.message || '删除' + data.name + '失败');
                    }
                }
                return result;
            }
        },

        /**
         * 初始化添加
         */
        handAdd: function (table, data, alert) {
            return function (result) {
                if (result.success) {
                    if (alert) {
                        utils.fixedAlert('success', '添加' + data.name + '成功');
                    }
                    table.api().draw();
                    if (table.analyse) {
                        table.analyse();
                    }
                } else {
                    if (alert) {
                        utils.fixedAlert('warning', result.message || '添加' + data.name + '失败');
                    }
                }
            }
        },

        /**
         * 添加
         */
        formAdd: function (table, data, handler) {
            var def = $.Deferred();
            var html = $(utils.getHtml('form_add', data));
            html.modal('show').on('hidden.bs.modal', function (e) {
                html.remove();
            });
            var form = $('form', html).formValidation(utils.getValidation(data.fields)).on('success.form.fv', function (e) {
                e.preventDefault();
                var $form = $(e.target), fv = $form.data('formValidation');
                data.fnServerData($form.serialize(), $form).then(function (result) {
                    if (result.success) {
                        html.modal('hide');
                    }
                    return result;
                }, function () {
                    utils.fixedAlert('warning', '添加' + data.name + '失败');
                }).then(handler || utils.handAdd(table, data, true)).always(function () {
                    if (fv.getSubmitButton()) {
                        fv.disableSubmitButtons(false);
                    }
                });
            });

            utils.initInputs(html, data, form);
            if (data.data) {
                form.data = data.data;
                form.unserialize(data.data);
            }
            def.resolve(form);

            return def;
        },

        /**
         * 初始化编辑
         * @data
         *  fields: 编辑的属性
         *  data: 原始数据
         *  name: 编辑的名字
         *  idx: 编辑行的下标
         *  fnServerData: post提交
         */
        handEdit: function (table, data, alert, toggle) {
            return function (result) {
                if (result.success) {
                    if (alert) {
                        utils.fixedAlert('success', '编辑' + data.name + '成功');
                    }
                    if (result.data) {
                        table.fnUpdate(result.data, data.idx, undefined, false);
                        if (toggle) {
                            toggle();
                        }
                    } else {
                        if (data.loadItem) {
                            data.loadItem().then(function (item) {
                                table.fnUpdate(item, data.idx, undefined, false);
                                if (toggle) {
                                    toggle();
                                }
                            });
                        }
                    }
                    if (table.analyse) {
                        table.analyse();
                    }
                } else {
                    if (alert) {
                        utils.fixedAlert('warning', result.message || '编辑' + data.name + '失败');
                    }
                }
                return result;
            }
        },

        /**
         * 编辑
         */
        formEdit: function (table, data, handler) {
            var def = $.Deferred();
            var fields = data.fields;
            for (var i in fields) {
                var validators = fields[i].validators;
                if (validators && validators.remote) {
                    validators.remote.data = function (validator) {
                        return {
                            id: validator.getFieldElements('id').val()
                        };
                    }
                }
            }
            var html = $(utils.getHtml('form_edit', data));
            html.modal('show').on('hidden.bs.modal', function (e) {
                html.remove();
            });
            var form = $('form', html).formValidation(utils.getValidation(data.fields)).on('success.form.fv', function (e) {
                e.preventDefault();
                var $form = $(e.target), fv = $form.data('formValidation');

                data.fnServerData($form.serialize(), $form).then(function (result) {
                    if (result.success) {
                        html.modal('hide');
                    }
                    return result;
                }, function () {
                    utils.fixedAlert('warning', '编辑' + data.name + '失败');
                }).then(handler || utils.handEdit(table, data, true)).always(function () {
                    if (fv.getSubmitButton()) {
                        fv.disableSubmitButtons(false);
                    }
                });
            });

            utils.initInputs(html, data, form);
            if (data.data) {
                form.data = data.data;
                form.unserialize(data.data);
            }
            def.resolve(form);
            return def;
        },

        /**
         * 选择编辑
         */
        formAssign: function (data, handle) {
            var def = $.Deferred();
            var html = $(utils.getHtml('form_assign', data));
            html.modal('show').on('hidden.bs.modal', function (e) {
                html.remove();
            });
            if (data.hidden_select !== true) {
                data.columns_arrays.push(["id", "选择", false, function () {
                    return '<a href="javascript:;" class="btn btn-primary btn-sm select-ope">选择</a>';
                }]);
            }
            var table = utils.dataTable(html, data).on('click', '.select-ope', function () {
                var rowData = table.fnGetData($(this).parents('tr').get(0));
                handle(rowData).then(function (result) {
                    if (result.success) {
                        if (!(data.notify === false)) {
                            utils.fixedAlert('success', '设置成功');
                        }
                        html.modal('hide');
                    } else {
                        utils.fixedAlert('warning', result.message || '设置失败');
                    }
                    return result;
                });
            });
            table.wrapperModal = html;
            def.resolve(table);
            return def;
        },

        /**
         * 初始化子表格
         */
        childWrapper: function (idx, tools, content) {
            return '<div class="child-wrapper" data-index="' + idx + '">' + (content || '') + '<div class="pull-right">' + utils.groupBtns(tools) + '</div></div>';
        },

        /**
         * 初始化切换子表格显示与隐藏
         */
        toggleChild: function (pane, checked, handler, html) {
            var storeChecked = store.get(location.hash + '-checked');
            if (storeChecked) {
                checked = storeChecked;
            }
            var btns = $('<div class="table-mode btn-group filter-list" data-name="toggle">' +
                '<button type="button" class="btn btn-primary btn-sm" data-value="0"><i class="fa fa-tripadvisor"></i> 浏览</button>' +
                '<button type="button" class="btn btn-primary btn-sm" data-value="1"><i class="fa fa-edit"></i> 编辑</button>' + (html || '') +
                '</div>');
            $('.btn[data-value="' + checked + '"]', btns).addClass('active');
            $('.dataTables_filter', pane).append(btns);
            $('.btn', btns).click(function () {
                $('.btn.active', btns).removeClass('active');
                checked = $(this).addClass('active').attr('data-value');

                store.set(location.hash + '-checked', checked);
                handler(checked);
            });
            return function () {
                handler(checked);
            }
        },

        /**
         * 树添加编辑开关
         */
        treeEditToggle: function (pane, tree) {
            var toggle = $('<i class="tree-edit-toggle fa fa-edit"></i>');
            toggle.click(function () {
                toggle.toggleClass('active');
                tree.jstree('refresh');
            });
            tree.on('click', '.fa-edit', function () {
                $(this).parents('.jstree-anchor').trigger('contextmenu');
                return false;
            });
            $('.split-left', pane).append(toggle);
            return toggle;
        },

        /**
         * 初始化树节点
         */
        handleTreeNodes: function (pane, feature, textName) {
            var tools = $('.tree-edit-toggle', pane).hasClass('active') ? '&nbsp;<i class="fa fa-edit"></i>' : '';
            return function (nodes) {
                handleTreeNodes(nodes, feature, tools, textName);
            }
        },

        /**
         * 批量处理
         * @param pane
         * @param handle
         */
        toggleBatch: function (pane, table, handle) {
            var wrapper = $('<div class="table-batch pull-left"></div>').appendTo($('.dataTables_length', pane));
            return function () {
                var checks = $(".checkbox:checked", table);
                if (!checks.length) {
                    return wrapper.html('');
                }
                handle(wrapper);
            }
        },

        /**
         * 获取选中值
         */
        checksValues: function (table, column) {
            var ids = [];
            $(".checkbox:checked", table).each(function () {
                if (column) {
                    ids.push($(this).attr(column));
                } else {
                    ids.push($(this).val());
                }
            });
            return ids;
        },

        /**
         * 弹出确认框
         */
        confirmation: function (obj, options) {
            var defaults = [['btnOkLabel', '确认'], ['btnCancelLabel', '取消'], ['href', 'javascript:;'], ['placement', 'left'], ['popout', true], ["onConfirm", function () {
                options.fnConfirm().then(function (result) {
                    if (options.optName) {
                        if (result.success) {
                            utils.fixedAlert('success', options.optName + '成功');
                        } else {
                            utils.fixedAlert('warning', result.message || options.optName + '失败');
                        }
                    }
                });
            }]];
            for (var i in defaults) {
                var ds = defaults[i];
                if (!options[ds[0]]) {
                    options[ds[0]] = ds[1];
                }
            }
            $(obj).confirmation(options).confirmation('show');
        },

        /**
         * 初始化上传
         */
        uploader: function (data) {
            requirejs(['public_uploader'], function (uploader) {
                uploader(data);
            });
        },

        /**
         * 坐标选择
         */
        map: function (data) {
            requirejs(['public_map'], function (map) {
                map(data);
            });
        },

        /**
         * 文章编辑
         */
        editor: function (data) {
            requirejs(['public_editor'], function (editor) {
                editor(data);
            });
        },

        /**
         * 转换成百度坐标
         */
        gcj2bd: function (res) {
            var lng = res.lng || res.longitude, lat = res.lat || res.latitude;
            var x_pi = 3.14159265358979324 * 3000.0 / 180.0;
            var z = Math.sqrt(lng * lng + lat * lat) + 0.00002 * Math.sin(lat * x_pi);
            var theta = Math.atan2(lat, lng) + 0.000003 * Math.cos(lng * x_pi);
            if (res.lng) {
                res.lng = z * Math.cos(theta) + 0.0065;
            } else {
                res.longitude = z * Math.cos(theta) + 0.0065;
            }
            if (res.lat) {
                res.lat = z * Math.sin(theta) + 0.006;
            } else {
                res.latitude = z * Math.sin(theta) + 0.006;
            }
            return res;
        },

        /**
         * 转换成GCJ坐标
         */
        bd2gcj: function (res) {
            var lng = res.lng || res.longitude, lat = res.lat || res.latitude;
            var x_pi = 3.14159265358979324 * 3000.0 / 180.0;
            var x = lng - 0.0065, y = lat - 0.006;
            var z = Math.sqrt(x * x + y * y) - 0.00002 * Math.sin(y * x_pi);
            var theta = Math.atan2(y, x) - 0.000003 * Math.cos(x * x_pi);
            if (res.lng) {
                res.lng = z * Math.cos(theta);
            } else {
                res.longitude = z * Math.cos(theta);
            }
            if (res.lat) {
                res.lat = z * Math.sin(theta);
            } else {
                res.latitude = z * Math.sin(theta);
            }
            return res;
        },

        /**
         * 初始化流程
         */
        initFlow: function (flows) {
            window.flows = flows;
        },

        /**
         * 流程值
         */
        flowValue: function (key) {
            return window.flows[key];
        },

        /**
         * 初始化字典
         */
        initDict: function (dicts) {
            window.dicts = dicts;
            window.dicts_map = {};
            for (var i in dicts) {
                var group = dicts[i];
                for (var j in group) {
                    window.dicts_map[i + '_' + group[j].value] = group[j];
                }
            }
        },

        /**
         * 初始化模块
         */
        initModule: function (modules) {
            window.modules = modules;

            var arr = [], barr = [];
            for (var i in modules) {
                var module = modules[i],
                    dict = {value: module.id, text: module.name},
                    bdict = {value: module.id, text: module.buy_sources};
                arr.push(dict);
                barr.push(bdict);

                window.dicts_map['modules_' + module.id] = dict;
                window.dicts_map['buy_sources_' + module.id] = bdict;
            }

            window.dicts.modules = arr;
            window.dicts.buy_sources = barr;
        },

        /**
         * 初始化模块
         */
        initStores: function (stores) {
            window.stores = stores;

            var arr = [];
            for (var i in stores) {
                var store = stores[i],
                    dict = {value: store.id, text: (store.alias || store.name)};
                arr.push(dict);

                window.dicts_map['store_' + store.id] = dict;
            }

            window.dicts.stores = arr;
        },

        /**
         * 模块值
         */
        moduleAttrs: function (key) {
            return window.modules[key].column_data;
        },

        /**
         * 字典单条记录
         */
        dict: function (type, value) {
            return window.dicts_map[type + '_' + value];
        },

        /**
         * 字典值
         */
        dictValue: function (type, value) {
            var dict = window.dicts_map[type + '_' + value];
            return dict ? dict.text : '';
        },

        /**
         * 初始化分屏
         * @param id
         * @param option
         */
        initSplit: function (id, option) {
            var initHeight = function () {
                var pane = $('#' + id);
                if (pane.length) {
                    var window_height = $(window).height();
                    $('.content', pane).height(window_height - $('.content-header', pane).outerHeight() - 63);
                } else {
                    $(window).unbind("resize", initHeight);
                }
            }
            $(window).resize(initHeight);
            initHeight();

            Split(['#' + id + ' .split-left', '#' + id + ' .split-right'], option);
        },

        /**
         * 初始化 Handlebars
         */
        initHandlebars: function () {
            Handlebars.registerHelper('dict', function (type, value) {
                return utils.dictValue(type, value);
            });

            Handlebars.registerHelper('dict_color', function (type, value) {
                return utils.dict(type, value).color;
            });

            Handlebars.registerHelper('if_eq', function (a, b, opts) {
                if (a == b)
                    return opts.fn(this);
                else
                    return opts.inverse(this);
            });

            Handlebars.registerHelper('if_has', function (a, b, opts) {
                if (b.indexOf(a) != -1)
                    return opts.fn(this);
                else
                    return opts.inverse(this);
            });

            Handlebars.registerHelper('format_datetime', function (datetime) {
                return utils.dateTimeFormat(datetime);
            });

            Handlebars.registerHelper('format_date', function (date) {
                return utils.dateFormat(date);
            });

            Handlebars.registerHelper('format_price', function (price) {
                if (price === undefined) return '';
                return price.toFixed(2);
            });

            Handlebars.registerHelper('inc', function (value) {
                return parseInt(value) + 1;
            });

            Handlebars.registerHelper('json', function (data) {
                return JSON.stringify(data);
            });

            Handlebars.registerHelper('multiply', function (a, b) {
                return (a * b).toFixed(2);
            });

            Handlebars.registerHelper('minus', function (a, b) {
                return (a - b).toFixed(2);
            });

            Handlebars.registerHelper('or', function (a, b) {
                return a || b;
            });

            Handlebars.registerHelper('discount', function (market, price) {
                return ((market - (market - price)) / market * 10).toFixed(1);
            });

            Handlebars.registerHelper('lesser', function (a, b, opts) {
                if (a < b)
                    return opts.fn(this);
                else
                    return opts.inverse(this);
            });

            Handlebars.registerHelper('anonymity', function (name) {
                return name[0] + '**' + (name.length > 2 ? name[name.length - 1] : '');
            });

            Handlebars.registerHelper('portrait', function (image) {
                if (!image) {
                    return '/images/portrait_default.png';
                }
                if (image.indexOf('wx.qlogo.cn') != -1) {
                    return image;
                }
                return image + '?imageView2/1/w/150/h/150/q/75';
            });
        },

        /**
         * 操作日志
         */
        showLogs: function (name, req) {
            var html = $(utils.getHtml('form_assign', {title: '操作日志 - ' + name}));
            html.modal('show').on('hidden.bs.modal', function (e) {
                html.remove();
            });
            var logsTable = utils.dataTable(html, {
                paginate: false,
                info: false,
                filter: false,
                columns_arrays: [
                    ["created_at", "操作时间", true, utils.dateTimeRender()],
                    ["opt", "操作", false, utils.dictRender('log_opt')],
                    ["role", "角色", false, utils.dictRender('log_role')],
                    ["user_id", "操作者", false, function (user_id, t, row) {
                        var user = row.user;
                        if (user) {
                            return '<div>' + (user.username || '') + '</div><div>' + user.tel + '</div>';
                        }
                        return '';
                    }],
                    ["ext_data", "数据", false, function () {
                        return '<a class="show-data" href="javascript:;" style="cursor: pointer;">显示数据</a>';
                    }]
                ],
                sorting: [[0, 'desc']],
                fnServerData: function () {
                    return req();
                }
            });

            logsTable.on('click', '.show-data', function () {
                var idx = logsTable.api().row($(this).parents('tr')).index();
                var rowData = logsTable.api().row(idx).data();

                $('.modal-body .data-wrapper', html).remove();
                $('.modal-body', html).append('<textarea class="data-wrapper form-control" style="width: 100%;">' + rowData.ext_data + '</textarea>');
            });
        },

        /**
         * 子表格
         */
        subTable: function (items, columns, opts) {
            var html = '<table class="table table-bordered sub-table"><thead><tr>';
            for (var i in columns) {
                html += '<th>' + columns[i][0] + '</th>';
            }
            html += '</tr></thead>';
            for (var i in items) {
                var item = items[i];
                html += '<tbody class="item-info" data-json=\'' + JSON.stringify(item) + '\'><tr class="' + (i % 2 ? 'odd' : 'even') + '">';
                for (var i in columns) {
                    var val = columns[i][1];
                    if (typeof val === 'string') {
                        html += '<td>' + item[val] + '</td>';
                    } else {
                        html += '<td>' + val(item) + '</td>';
                    }
                }
                html += '</tr>' + (opts ? '<tr><td colspan="8">' + utils.groupBtns(opts) + '</td></tr>' : '') + '</tbody>';
            }
            html += '</table>';
            return html;
        }

    }

    window.utils = utils;
}();